package com.newmainsoftech.dao.entity.relation;

import java.io.Serializable;
import java.util.Calendar;

import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Transient;

@Entity
public class VariableHashHoldeeEntity implements HoldeeSide<VariableHashHolderEntity>, Serializable {
	private static final long serialVersionUID = 1L;
	
	@Transient
	public static final String IdColumnName = "id";
		/** @return {@value #IdColumnName}
		 */
		public static String getIdColumnName() {
			return IdColumnName;
		}
	
	@Id
	@Basic( optional = false)
	@Column( name = VariableHashHoldeeEntity.IdColumnName)
	private String id;
		public String getId() {
			return id;
		}
		public void setId( final String id) {
			this.id = id;
		}
	
	@Transient
	boolean isEnsureIdentityCalled = false;
		public boolean isEnsureIdentityCalled() {
			return isEnsureIdentityCalled;
		}
		public void setEnsureIdentityCalled( boolean isEnsureIdentityCalled) {
			this.isEnsureIdentityCalled = isEnsureIdentityCalled;
		}

	@Override
	public void ensureIdentity() {
		setEnsureIdentityCalled( true);
	}

	@Transient
	public static final String HolderJoinColumnName = "holder_id";
		/** @return {@value #HolderJoinColumnName}
		 */
		public static String getHolderJoinColumnName() {
			return HolderJoinColumnName;
		}
	@ManyToOne( optional = true, 
			cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.DETACH, CascadeType.REFRESH})
	@JoinColumn( name = VariableHashHoldeeEntity.HolderJoinColumnName,
			referencedColumnName = VariableHashHolderEntity.IdColumnName)
	private VariableHashHolderEntity holderEntity;
		@Override
		public VariableHashHolderEntity getHolderEntity() {
			return holderEntity;
		}
		@Override
		public void setHolderEntity( final VariableHashHolderEntity holderEntity) {
			this.holderEntity = holderEntity;
		}
	
	// hashCode and equals methods based on value of id member field ----------------------
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		return result;
	}
	
	@Override
	public boolean equals(Object obj) {
		if (this == obj) return true;
		if (obj == null) return false;
		if (getClass() != obj.getClass()) return false;
		
		VariableHashHoldeeEntity other = (VariableHashHoldeeEntity) obj;
		if (id == null) {
			if ( other.id != null) return false;
		} 
		else if ( !id.equals( other.id)) return false;
		
		return true;
	}
	// ------------------------------------------------------------------------------------
		
	public VariableHashHoldeeEntity() {
		String idStr 
		= String.valueOf( Thread.currentThread().getId())
			.concat( "_").concat( String.valueOf( Calendar.getInstance().getTimeInMillis()))
			.concat( "_").concat( Integer.toHexString( System.identityHashCode( this)));
		setId( idStr);
			// As long as each test clean up every created VariableHashHolderEntity entities at end of 
			// test, this idStr value can assure uniqueness even in multi-threaded test environment.    
	}
	
	@Override
	public String toString() {
		String holderEntityStr = "null";
			if ( holderEntity != null) {
				holderEntityStr
				= holderEntity.getClass().getSimpleName()
					.concat( "@" + Integer.toHexString( System.identityHashCode( holderEntity)));
					// Did not use toString method to assign value to holderEntityStr in order 
					// to avoid loop.  
			}
		return this.getClass().getSimpleName()
				.concat( "@" + Integer.toHexString( System.identityHashCode( this)))
				.concat( "[id=" + id)
				.concat( ", holderEntity=" + holderEntityStr)
				.concat( "]");
	}
}